/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package BusinessLayer;

import AccessLayer.*;
import Helper.md5;
import Objekte.AuctionProdukt;
import Objekte.Produkt;
import Objekte.User;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.logging.Level;
import logging.Logger;
import XMLStuff.*;
import java.beans.XMLEncoder;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Locale;
import javax.swing.ImageIcon;

/**
 *
 * @author benji
 */
public class BusinessLayer {

    private static AccessLayer access = null;
    private static boolean loggedIn = false;
    private static int userId;
    private static md5 md5 = new md5();

    public static void saveAsXML() {
        FileOutputStream out = null;
        XMLEncoder encoder = null;

        ArrayList<Produkt> produkte = new ArrayList<Produkt>();
        for (webservice.Produkt p : access.getProdukteByUserId(BusinessLayer.userId)) {
            produkte.add(createBusinessProduct(p));
        }

        XMLBlob so = new XMLBlob(BusinessLayer.userId, access.getPasswordHash(BusinessLayer.userId), access.getGuthaben(BusinessLayer.userId), access.getRankCount(), produkte);
        try {
            out = new FileOutputStream("SaveGame.xml");
            encoder = new XMLEncoder(out);
            encoder.writeObject(so);
            //encoder.writeObject(new JButton("Hallo"));
        } catch (FileNotFoundException ex) {
            Logger.error("Fehker beim oeffnen der Datei", ex);
        } finally {
            if (encoder != null) {
                encoder.close();
                try {
                    out.close();
                } catch (IOException ex) {
                    Logger.fatal("IO Exception in saveAsXML", ex);
                }
            }
        }


    }

    public static void parseXML(File sf) {
//        FileInputStream fis;
//        try {
//            fis = new FileInputStream(sf);
//            ObjectInputStream ois = new ObjectInputStream(fis);
//            XMLBlob blob = ois.readObject();
//        }
//        catch (FileNotFoundException ex) {
//            java.util.logging.Logger.getLogger(BusinessLayer.class.getName()).log(Level.SEVERE, null, ex);
//        }
//        catch (IOException ex) {
//            java.util.logging.Logger.getLogger(BusinessLayer.class.getName()).log(Level.SEVERE, null, ex);
//        }




        int guthaben = 0;
        int userID = 0;
        int rank = 0;
        //produktliste
        ArrayList<Produkt> produktListe = new ArrayList<Produkt>();
        //einzeles produkt
        Produkt produkt = new Produkt();

        XMLParser xml = new XMLParser(sf.getAbsolutePath(), "java");
        for (XMLParser oXml : xml.children("object")) {
            for (XMLParser voidXml : oXml.children("void")) {
                if (voidXml.string("property").equals("guthaben")) {
                    XMLParser guthabenXml = voidXml.child("int");
                    guthaben = Integer.parseInt(guthabenXml.content());
                }
                if (voidXml.string("property").equals("id")) {
                    XMLParser idXml = voidXml.child("int");
                    userID = Integer.parseInt(idXml.content());
                }
                if (voidXml.string("property").equals("rank")) {
                    XMLParser rankXml = voidXml.child("int");
                    rank = Integer.parseInt(rankXml.content());
                }
                if (voidXml.string("property").equals("userProduktListe")) {
                    XMLParser produktListXml = voidXml.child("void");
                    for (XMLParser produktXML : produktListXml.children("object")) {
                        for (XMLParser produktAttXML : produktXML.children("void")) {
                            if (produktAttXML.string("property").equals("ID")) {
                                XMLParser idXml = produktAttXML.child("int");
                                produkt.setID(Integer.parseInt(idXml.content()));
                            }
                            if (produktAttXML.string("property").equals("amount")) {
                                XMLParser amountXml = produktAttXML.child("int");
                                produkt.setAmount(Integer.parseInt(amountXml.content()));
                            }
                            if (produktAttXML.string("property").equals("description")) {
                                XMLParser descriptionXml = produktAttXML.child("string");
                                produkt.setDescription(descriptionXml.content());
                            }
                            if (produktAttXML.string("property").equals("name")) {
                                XMLParser nameXml = produktAttXML.child("string");
                                produkt.setName(nameXml.content());
                            }
                            if (produktAttXML.string("property").equals("price")) {
                                XMLParser priceXml = produktAttXML.child("int");
                                produkt.setPrice(Integer.parseInt(priceXml.content()));
                            }
                            if (produktAttXML.string("property").equals("requiredRank")) {
                                XMLParser requiredRankXml = produktAttXML.child("int");
                                produkt.setRequiredRank(Integer.parseInt(requiredRankXml.content()));
                            }
                        }

                    }
                    produktListe.add(produkt);
                    //System.out.println(produkt.getAmount() + ", " + produkt.getName());
                }
            }
        }
        XMLBlob blob = new XMLBlob(userId, null, guthaben, rank, produktListe);
        User u = new User();
        u.setId(userId);
        u.setGuthaben(guthaben);
        u.setRank(rank);
        int j = 0;
        webservice.Produkt[] produkte = new webservice.Produkt[produktListe.size()];
        for (Produkt p : produktListe) {
            produkte[j] = createWebserviceProduct(p);
            j++;
        }


        access.writeSaveGameIntoDatabase(createWebserviceUser(u), produkte);
    }

    /******************************************
     *      NEU
     * ----------------------------------
     *      ALT
     ******************************************/
    /**
     * Get Produkt Statistik
     * @param iD
     * @return
     */
    public static int getProduktStatistik(int iD) {
        return access.getProduktStatistik(iD);
    }

    /**
     * liest aus den Properties ob eine Datenbank oder der Mock verwendet werden soll
     */
    public BusinessLayer() {
//        Properties p = AccessLayer.giveConfig();
//        int i = Integer.parseInt(p.getProperty("DatabaseType"));
//        Logger.info("Lese aus Properties ob DB od. Mock");
//        switch (i) {
////            case 1:
////                access = new Mock();
////                Logger.info("Arbeite mit Mock");
////                break;//Mock;
////            case 2:
////                access = new DB();
////                Logger.info("Arbeite mit DB");
////                break;//DB
//            case 3:
        access = new WebService();
        Logger.info("Arbeite mit Hibernate");
//                break;
//            default:
//        }

    }

    public static void refresh() {
        access.refresh();
    }

    /**
     * Returniert als Reporting den Umsatz des Users
     * @return
     */
    public static int getUmsatzProTag() {
        return access.getUmsatzProTag(BusinessLayer.userId);
    }

    public static String getRegisterDate() {
        Logger.info("Business - getRegisterDate");
        return access.getRegisterDate(getUserId());
    }

    public static ArrayList<Produkt> searchItem(String name) {
        Logger.info("Business - search Item by name");
        ArrayList<Produkt> itemList = new ArrayList<Produkt>();
        for (webservice.Produkt p : access.searchItemName(name)) {
            itemList.add(createBusinessProduct(p));
        }

        return itemList;
    }

    public static ArrayList<Produkt> searchItem(int preis) {
        Logger.info("Business - search item by price");
        ArrayList<Produkt> itemList = new ArrayList<Produkt>();
        for (webservice.Produkt p : access.searchItemPrice(preis)) {
            itemList.add(createBusinessProduct(p));
        }

        return itemList;
    }

    public static ArrayList<Produkt> searchItem(String name, int preis) {
        Logger.info("Business - search item by price and name");
        ArrayList<Produkt> itemList = new ArrayList<Produkt>();
        for (webservice.Produkt p : access.searchItemPriceAndName(name, preis)) {
            itemList.add(createBusinessProduct(p));
        }

        return itemList;
    }

    public static int bid(int auctionId, int amount) {
        Logger.info("Business - Biete");
        return access.bid(auctionId, getUserId(), amount);
    }

    /**
     * prüft ob der angegebene user bereits existiert
     * damit nicht der selbe username zwei mal existiert
     * @param name
     * @return
     */
//    public static boolean existsUser(String name) {
//        ArrayList<User> userList = BusinessLayer.getUserList();
//        boolean nameIsUsed = false;
//            for(User u : userList){
//                if(name.equals(u.getName())){
//                        Logger.user("Name eistiert bereits");
//                        nameIsUsed = true;
//                        break;
//                }
//            }
//        return nameIsUsed;
//    }
    public static int startAuction(Produkt p, int amount, int dauer) {
        Logger.info("Business - Starte auktion");
        return access.startAuction(createWebserviceProduct(p), amount, getUserId(), dauer);
    }

    public static int startAuctionAsAdmin(Produkt p, int amount, int dauer) {
        Logger.info("Business - starte Auktion als admin");
        return access.startAuctionAsAdmin(createWebserviceProduct(p), amount, getUserId(), dauer);
    }

    public static void deleteUser(User u) {
        Logger.info("Business - Admin - lösche user");
        access.deleteUser(createWebserviceUser(u));
    }

    public static void updateUser(User u) {
        Logger.info("Business - update user");
        access.updateUser(createWebserviceUser(u));
    }

    public static void SaveItem(Produkt p) {
        Logger.info("Business - Admin - SaveItem()");
        access.saveItem(createWebserviceProduct(p));
    }

    public static void deleteItem(Produkt p) {
        Logger.info("Business - Admin - lösche Item");

        access.deleteItem(createWebserviceProduct(p));
    }

    public static void updateItem(Produkt p) {
        Logger.info("Business - Admin - UpdateItem");
        access.updateItem(createWebserviceProduct(p));
    }

    public static void changeUsername(String name, int userId) {
        Logger.info("Business - Change username");
        access.changeUsername(name, userId);
    }

    /**
     * um Passwort zu verändern
     * hier wird das Plaintext passwort in einen hashwert umgewandelt
     * @param newPassword
     * @param userId
     */
    public static void changePassword(String newPassword, int userId) {
        Logger.info("Business - Change Passwort");
        String password = md5.getmd5(newPassword);
        access.changePassword(password, userId);
    }

    public static String getRank(int userId) {
        Logger.info("Business - getRank");
        return access.getRank(userId);
    }

    public static int getRankCount() {
        Logger.info("Business - CountRanks");
        return access.getRankCount();
    }

    public static boolean isAdmin(int userId) {
        Logger.info("Business - ist der User ein Amdin");
        if (access.isAdmin(userId)) {
            Logger.info("Business - User ist ein Admin");
            return true;
        } else {
            Logger.info("Business - User ist kein Amdin");
            return false;
        }
    }

    public static int getUserId() {
        Logger.info("Business - getUserID");
        return userId;
    }

    public static void setUserId(int userId) {
        Logger.info("Business - setUserID");
        BusinessLayer.userId = userId;
    }

    public static boolean isLoggedIn() {
        Logger.info("Business - isLoggedIn");
        return loggedIn;
    }

    public static void setLoggedIn(boolean loggedIn) {
        Logger.info("Business - setLoggedIn");
        BusinessLayer.loggedIn = loggedIn;
    }

    public static String getUser(int userId) {
        Logger.info("Business - getUser - name");
        return access.getUserName(userId);
    }

    /**
     *um die userid eines Users zu erhalten
     * nur mit:
     * @param user username
     * @param password passwort des Users
     * -> wird hier in einen hash wert umgewandelt
     * @return die userid
     */
    public int getUserId(String user, String password) {
        Logger.info("Business - getUserID mit (username, passwort");
        password = md5.getmd5(password);
        return access.getUserId(user, password);
    }

    /**
     * checkt ob der user existiert und er sich anmelden darf
     * @param user
     * @return true wenn user existiert
     */
    public static boolean checkUser(String user) {
        Logger.info("Business - checkUser - für login");
        boolean isUser = false;
        if (user.equals(access.checkUser(user))) {
            Logger.debug("IsUser true");
            isUser = true;
        }
        return isUser;
    }

    /**
     * für die anmeldung checkt ob das passwort zu dem User passt
     * @param user
     * @param password
     * @return true wenn das PAsswort korrekt ist
     */
    public static boolean checkPassword(String user, String password) {
        Logger.info("Business - checkPasswort - für login");
        boolean isPassword = false;
        String pwHash = null;
        pwHash = md5.getmd5(password);
        if (checkUser(user)) {
            if (pwHash.equals(access.checkPassword(user, pwHash))) {
                isPassword = true;
                Logger.debug("checkPassword - True");
            }
        }
        return isPassword;
    }

    public static void abmelden() {
        Logger.info("Business - abmelden");
        userId = -1;
        Logger.info("LogOff");
    }

    public static int getGuthaben(int userId) {
        Logger.info("Business - getGuthaben");
        return access.getGuthaben(userId);
    }

    public static int produce(Produkt p, int amount) {
        Logger.info("Business - produce");
        return access.produce(createWebserviceProduct(p), amount, getUserId());
    }

    /**
     *Registrierern
     * @param username neuer name
     * @param password neues passwort
     * @param passwordRepeat
     * @return 0 alles ok
     * @return 1 die zwei passwörter stimen nicht überein
     * @return 2 der Username existiert in der DB schon
     */
    public static int register(String username, String password, String passwordRepeat) {
        Logger.info("Business - Register");
        //nachschauen ob username schon vorhanden
        if (!password.equals(passwordRepeat)) {
            Logger.warn("Passwords not matching");
            return 1;
        }
        if (username.equals(access.checkUser(username))) {
            Logger.warn("User exists already");
            return 2;
        }
        //registrieren
        password = md5.getmd5(password);
        access.newUser(username, password);
        return 0;
    }

    public static ArrayList<Produkt> GetProductList(int userId) {
        Logger.info("Business - getProduktlist - von einem User");
        ArrayList<Produkt> produkte = new ArrayList<Produkt>();
        webservice.Produkt[] pr = access.getProdukteByUserId(BusinessLayer.userId);
        for (webservice.Produkt produkt : pr) {
            produkte.add(createBusinessProduct(produkt));
        }
        return (ArrayList<Produkt>) produkte;
    }

    public static ArrayList<Produkt> GetProductList() {
        Logger.info("Business - getProduktliste - alle Produkte - admin");
        ArrayList<Produkt> produkte = new ArrayList<Produkt>();
        webservice.Produkt[] pr = access.getProdukte();
        for (webservice.Produkt produkt : pr) {
            produkte.add(createBusinessProduct(produkt));
        }
        return produkte;
    }

    public static ArrayList<AuctionProdukt> getAuctionLItemist() {
        Logger.info("Business - getAuctionList");
        webservice.AuctionProdukt[] pr = access.getAuctionItemList();
        ArrayList<AuctionProdukt> produkte = new ArrayList<AuctionProdukt>();
        for (webservice.AuctionProdukt auctionProdukt : pr) {
            produkte.add(createBusinessAuctionProducts(auctionProdukt));
        }
        return produkte;
    }

    public static ArrayList<User> getUserList() {
        Logger.info("Business - getUserList");
        ArrayList<User> user = new ArrayList<User>();
        for (webservice.User u : access.getUserList()) {
            user.add(createBusinessUser(u));
        }
        return user;
    }

    //*************************
    //********
    //******* Businessobjekte - Umwandlung
    //********
    //*************************
    private static AuctionProdukt createBusinessAuctionProducts(webservice.AuctionProdukt ap) {

        AuctionProdukt api = new AuctionProdukt();
        api.setAmount(ap.getAmount());
        api.setAuctionid(ap.getAuctionid());
        api.setCurrent_bid(ap.getCurrentBid());
        api.setHighest_bidder(ap.getHighestBidder());
        api.setPerson(ap.getPerson());
        api.setProduct(ap.getProduct());
        SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm", Locale.GERMANY);
        try {
            api.setTtl(new Timestamp(format.parse(ap.getTtl()).getTime()));
        } catch (ParseException ex) {
            java.util.logging.Logger.getLogger(BusinessLayer.class.getName()).log(Level.SEVERE, null, ex);
        }
        api.setProduct(ap.getProduct());
        return api;
    }

    private static Produkt createBusinessProduct(webservice.Produkt p) {
        Produkt pr = new Produkt();
        pr.setAmount(p.getAmount());
        pr.setDescription(p.getDescription());
        pr.setID(p.getID());
        pr.setName(p.getName());
        pr.setPrice(p.getPrice());
        pr.setRequiredRank(p.getRequiredRank());
        if (p.getImage() != null) {
            ImageIcon i = new ImageIcon(p.getImage());
            pr.setIcon(i);
        }
        return pr;
    }

    private static User createBusinessUser(webservice.User user) {
        User us = new User();
        us.setAnmeldeDatumString(user.getAnmeldeDatumString());
        us.setGuthaben(user.getGuthaben());
        us.setId(user.getId());
        us.setIsAdmin(user.isIsAdmin());
        us.setIsOnline(user.isIsOnline());
        us.setName(user.getName());
        us.setPwHash(user.getPwHash());
        us.setRan_string(user.getRanString());
        us.setRank(user.getRank());
        us.setRankString(user.getRankString());
        return us;
    }

    private static webservice.Produkt createWebserviceProduct(Produkt p) {
        webservice.Produkt pr = new webservice.Produkt();
        pr.setAmount(p.getAmount());
        pr.setDescription(p.getDescription());
        pr.setID(p.getID());
        pr.setName(p.getName());
        pr.setPrice(p.getPrice());
        pr.setRequiredRank(p.getRequiredRank());
        if (p.getImagePath() != null) {
            InputStream is = null;
            byte[] bytes = null;
            try {
                File f = new File(p.getImagePath());
                is = new FileInputStream(f);

                int offset = 0;
                int numRead = 0;
                bytes = new byte[(int) f.length()];
                while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
                    offset += numRead;
                }
                if (offset < bytes.length) {
                    throw new IOException("Could not completely read file " + f.getName());
                }
            } catch (IOException ex) {
                java.util.logging.Logger.getLogger(BusinessLayer.class.getName()).log(Level.SEVERE, null, ex);
            }finally {
                try {
                    is.close();
                } catch (IOException ex) {
                    java.util.logging.Logger.getLogger(BusinessLayer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            pr.setImage(bytes);
        }
        return pr;
    }

    private static webservice.User createWebserviceUser(User u) {
        webservice.User us = new webservice.User();
        us.setAnmeldeDatumString(u.getAnmeldeDatumString());
        us.setGuthaben(u.getGuthaben());
        us.setId(u.getId());
        us.setIsAdmin(u.isIsAdmin());
        us.setIsOnline(u.isIsOnline());
        us.setName(u.getName());
        us.setPwHash(u.getPwHash());
        us.setRanString(u.getRan_string());
        us.setRank(u.getRank());
        us.setRankString(u.getRankString());
        return us;
    }
}
